import Parser = require('./../base/Parser');
import GCJ_CLASS_TYPE = require('./../../common/GCJ_CLASS_TYPE');
import DEFINE = require('./../../common/DEFINE');
import ObjBase = require('./ObjBase');
import TextExtObj=require('./TextExtObj');
import PageInfo=require('./../../common/PageInfo');
import ImageObj=require('./ImageObj');
import Point=require('./../../common/graph/Point');
import CommonModel = require('./../../common/model/CommonModel');
import ObjManager = require('./../cont/ObjManager');
import ObjPosition = require('./../base/ObjPosition');
import ObjPositionAlign = require('./../base/ObjPositionAlign');
import ObjRelativePosType = require('./../base/ObjRelativePosType');
import TextObj=require('./TextObj');
import SJGReplaceGroup = require('./../replace/SJGReplaceGroup');
import SJGReplaceGroupAdvance = require('./../replace/SJGReplaceGroupAdvance');

var path=require('path');
var CommonUtil=require('../../../../common/util/CommonUtil');
var async  = require( 'async'); // 同步控制
var fs = require('fs')
var CONFIG=require('../../../../common/config');

export  = GroupObj;

/**
 *
 * @author 
 *
 */
class GroupObj extends ObjBase{
    public children: Array<ObjBase> = new Array<ObjBase>(); 
    public constructor(g?) {
        super(g);
        
        this.ct = GCJ_CLASS_TYPE.CLASS_TYPE_GroupObj;
	}
	
    // 从json对象(注意不是json字符串)中解析
	// 参数：self,true表示只拷贝自身数据，而不拷贝子的数据
    public fromJson(jsonObj,versionId,self?) { 
        super.fromJson(jsonObj,versionId,self);
        
        var copyChild: Boolean=self? false:true;
        if(copyChild&& jsonObj.children){ 
            for ( var i = 0; i < jsonObj.children.length;i++){
                var one:ObjBase =<ObjBase> Parser.fromUnknownJson( jsonObj.children[i], versionId, this.getGlobalData() );
                if(one){
                    this.children.push( one );
                    one.parent=this;// 建立子对父的引用
                }
            }
        }
        
        // 加载文档时
        if (this.getGlobalData().docStatus() == DEFINE.DOC_STATUS_LOADING) {
            this.getGlobalData().objManager().saveObject(this);
        }
                
    }
    // 最小化TextExt转换成Json:所有页root对象只保留TextExtObj(且只保留fz\te\style\color\id\pos几个属性)
    public toJsonOfMinTextExt(): string {
        // 去掉父json字符串的头尾
        var superJson =super.toJsonOfMinTextExt();
        superJson=superJson.substr(1,superJson.length-2);

        var ret ="{";
        ret+=superJson;

        // children
        ret+=",";
        ret+="\"children\":";
        ret+="[";
        var first =true;
        for(var i =0;i<this.children.length;i++){
            var childJson =this.children[i].toJsonOfMinTextExt();
            if(childJson.length==0) continue; // 不纪录空字符串

            if(!first) {
                ret+=",";
            }
            ret+=childJson;
            first=false;
        }
        ret+="]";


        ret+="}";
        return ret;
    }
    // 转成json字符串
    public toJson():string {
        // 去掉父json字符串的头尾
        var superJson = super.toJson();
        superJson = superJson.substr(1,superJson.length-2);
                        
        var ret = '{';
        ret +=superJson;
                            
        // children
        ret +=',';
        ret += '"children":';
        ret += '[';
        for ( var i = 0; i < this.children.length;i++){
            if(i>0){
                ret += ',';
            }
            ret += this.children[i].toJson();
        }
        ret += ']';
                
        ret+='}';
        return ret;
    }
    
    // 添加子对象，能够添加子对象的对象重载
    public addChild(child: ObjBase,insertIndex: number,flag: number=0): boolean {
         if ((insertIndex<0) || (insertIndex>this.children.length)){
             return false;     
         }
         this.children.splice( insertIndex, 0, child );
         child.parent=this; // 建立子对父的引用
         return true;
    }
    //  获得子对象的id，能够添加子对象的对象重载
    public getChildIds(): Array<number> {
        var ret: Array<number>=new Array<number>();
        
        for(var i in this.children) {
            ret.push(this.children[i].id);
        }
        return ret;
    }
    // 获得某种类型的子对象，能够添加子对象的对象重载
    public getChildOfType(ct: number,reverse: Boolean=false,recursive: Boolean=false): Array<number> {
        var ret: Array<number>=new Array<number>();

        for(var i in this.children) {
            var one=this.children[i];
            if(reverse){
                if(one.ct!=ct) {
                    ret.push(one.id);
                }                
            }else{
                if(one.ct==ct) {
                    ret.push(one.id);
                }
            }
            
            // 处理递归
            if(recursive) { 
                var subRet: Array<number> = one.getChildOfType(ct,reverse,recursive);
                if(subRet.length>0) {
                    ret=ret.concat(subRet);
                }                
            }
        }
        return ret;
    }
    public getChildObjOfType(ct: number,reverse: Boolean=false,recursive: Boolean=false): Array<ObjBase> {
        var ret: Array<ObjBase>=new Array<ObjBase>();

        for(var i in this.children) {
            var one=this.children[i];
            if(reverse) {
                if(one.ct!=ct) {
                    ret.push(one);
                }
            } else {
                if(one.ct==ct) {
                    ret.push(one);
                }
            }

            // 处理递归
            if(recursive) {
                var subRet: Array<ObjBase>=one.getChildObjOfType(ct,reverse,recursive);
                if(subRet.length>0) {
                    ret=ret.concat(subRet);
                }
            }
        }
        return ret;
    }
    // 获得某种类型的子对象，能够添加子对象的对象重载
    public getChildOfTypes(cts: Array<number>,reverse: Boolean=false,recursive: Boolean=false): Array<number> {
        var ret: Array<number>=new Array<number>();

        for(var i in this.children) {
            var one=this.children[i];
            if(reverse) {
                if(cts.indexOf(one.ct)<0) {
                    ret.push(one.id);
                }
            } else {
                if(cts.indexOf(one.ct )>=0) {
                    ret.push(one.id);
                }
            }
            
            // 处理递归
            if(recursive) {
                var subRet: Array<number>=one.getChildOfTypes(cts,reverse,recursive);
                if(subRet.length>0) {
                    ret=ret.concat(subRet);
                }
            }
        }
        return ret;
    }
    // 删除子对象，能够添加子对象的对象重载
    public removeChild(id:number){
        for(var i in this.children){
            var child: ObjBase=<ObjBase>this.children[i];
            if(child.id==id) {
                this.children.splice(i,1);
                child.parent=null; // 建立子对父的引用
                return;
            } else { 
                child.removeChild(id);
            }
        }
    }
    // 删除子对象，能够添加子对象的对象重载
    public removeChilds(ids: Array<number>) {
        for(var i in ids){ 
            this.removeChild(ids[i]);
        }
    }
    // 删除所有子对象，能够添加子对象的对象重载
    public removeAllChild(){
        this.children.splice(0,this.children.length);  
        
        for(var i in this.children){
            var child: ObjBase=<ObjBase>this.children[i];
            child.parent=null; // 删除子对父的引用
        }
    }
    // 更新对子对象的引用
    public updateChildRef(id:number, ref:ObjBase){
        for(var i in this.children) {
            var child: ObjBase=<ObjBase>this.children[i];
            if(child && child.id==id){
                this.children[i]=ref;
                ref.parent=this;
                break;
            }
        }
    }
    
    // 扩展大小
    // 参数：controlType 控制点类型
    // 参数：ratioX x缩放比例
    // 参数：ratioY y缩放比例
    // 参数：outside true表示操作所在的最外层对象，false表示内部对象
    public expand(controlType:number,ratioX: number,ratioY: number,outside:boolean){
        super.expand(controlType,ratioX,ratioY,outside);
               
        
        var len=this.children.length;
        for ( var i = 0; i < len;i++){
            var one: ObjBase=<ObjBase> (this.children[i]);
            one.expand(controlType,ratioX,ratioY,false);
            
        }
           
    }
    
    // 是否简单对象[非Group对象，非以及Group对象的派生]
    public isSimple():boolean{
        return false;
    }
    
    // 上移／下移一层
    // 参数：obj 从父对象中删除obj
    // 参数：up true向上移动
    public MSG_UI_MOVE_UP_DOWN(obj: ObjBase,up: Boolean) {
        if(this.children.length<=1){
            return;
        }
        
        var index:number = this.children.indexOf(obj);
        if(up){
            if(index < this.children.length-1) {
                this.children.splice(index,1);
                this.children.splice(index+1,0,obj);

            }
        }else{
            if(index > 0) {
                if(index==1) {
                    // 不能移动到背景组之下
                    var firstObj=this.children[0];
                    if(firstObj!=null && firstObj.pagebk==ObjBase.PAGE_BACKGROUND_YES) {
                        return;
                    }
                }
                
                this.children.splice(index,1);
                this.children.splice(index-1,0,obj);

            }
        }
        
    }
    
    // 获取对象名称
    public getObjetName(): string {
        var name="编组";
        if (this.pagebk==ObjBase.PAGE_BACKGROUND_YES) {
            name+="[页背景]";
        }
        return name;
    }
    
    // 设置lock为非锁定状态
    public clearLock() {
        super.clearLock();
        
        var len=this.children.length;
        for(var i=0;i<len;i++) {
            var one: ObjBase=<ObjBase> this.getGlobalData().objManager().getObject(this.children[i].id);
            one.clearLock();
        }
    }
    
    // 缩放对象
    public scale(s: number) {
        super.scale(s);
        var len=this.children.length;
        for(var i=0;i<len;i++) {
            var child: ObjBase=<ObjBase>this.children[i];
            child.scale(s);
        }
    }
    
    // 将多个对象打组
    public static groupFrom(objs: Array<ObjBase>,objMgr: ObjManager): GroupObj {
        var grp: GroupObj=new GroupObj();
        objMgr.saveObject(grp,true);
        grp.children=grp.children.concat(objs);
        // 计算编组中元素的最大值／最小值
        var minx: number=0,maxx: number=0,
            miny: number=0,maxy: number=0;
        for(var i=0;i<objs.length;i++){
            var one: ObjBase=objs[i];
            if(i==0){
                minx=one.pos.x;
                miny=one.pos.y;
                maxx=one.pos.x;
                maxy=one.pos.y;
            }else{
                minx=minx<one.pos.x?minx:one.pos.x;
                miny=miny<one.pos.y?miny:one.pos.y;

                var mx=(one.pos.x+one.pos.w);
                maxx=maxx>mx? maxx:mx;
                var my=(one.pos.y+one.pos.h);
                maxy=maxy>my? maxy:my;       
            }
        }
        // 更新编组的尺寸和位置的信息
        grp.pos.x=minx;
        grp.pos.y=miny;
        grp.pos.w=maxx-minx;
        grp.pos.h=maxy-miny;
        
        // 更新编组多子的尺寸和位置的信息
        for(var i=0;i<objs.length;i++) {
            var one: ObjBase=objs[i];
            one.pos.x-=minx;
            one.pos.y-=miny;
        }
        
        
        

        return grp;
    }

    // 转换成CommonModel树
    public toCommonModel(level: number): CommonModel {
        var m=super.toCommonModel(level);
        
        var len=this.children.length;
        for(var i=0;i<len;i++) {
            var child: ObjBase=<ObjBase>this.children[i];
            var ms = child.toCommonModel(level+1);
            m.addChild(ms);
        }
            
        return m;
    }
    // 深度更新id［处理自身和子对象，递归］
    // 参数：idMaps，新旧id的对应关系, 例如：[{oldId:1,newId:2}]
    public deepResetId(idMaps: Array<any>) {
        super.deepResetId(idMaps);
        
        
        // 更新子
        var len=this.children.length;
        for(var i=0;i<len;i++) {
            var child: ObjBase=<ObjBase>this.children[i];
            child.deepResetId(idMaps);
        }
    }
    // 计算子的bbox
    public childBBox(): ObjPosition{
        var ret: ObjPosition=new ObjPosition();
        
        for(var m in this.children) {
            if(m==0) {
                ret.copy(this.children[m].pos);
            } else {
                ret.union(this.children[m].pos);
            }
        }
        
        return ret;
    }
    // 根据参数计算内部数据：例如文字根据字体字号计算轮廓
    public refresh(replace: SJGReplaceGroup=null) {
        // 更新子
        for(var i in this.children){
            var one: ObjBase=this.children[i];
            one.refresh(replace);
        }
        
        // 根据align调整 内部对象的布局
        if(this.parent.ct == GCJ_CLASS_TYPE.CLASS_TYPE_ReplaceGroupObj){
            this.adjustLayoutOfReplaceGroup(replace);    
        }        
    }
    // 根据kernelObj上的对齐属性调整内部对象的布局
    public adjustLayoutOfReplaceGroup(replace: SJGReplaceGroup=null): void {
        // 如果自身没有对齐信息，则不处理
        if(this.align==null) return;
        // 无子对象，则不处理
        if(this.children.length==0) return;
        
        // 处理子对象
        this.adjustLayoutOfReplaceGroup_child(replace);
            
        
    }
    // 根据kernelObj上的对齐属性调整内部对象的布局
    private adjustLayoutOfReplaceGroup_child(replace: SJGReplaceGroup=null): void {
        // 普通对齐
        if(replace.advance.force_align==SJGReplaceGroupAdvance.FORCE_ALIGN_NONE){
            
            // 普通对齐时只处理单个文字
            if(this.children.length==1&&(this.children[0] instanceof TextExtObj)) {
                // 普通对齐时 只有圆形扩展和对角线扩展 需要调整文字的对齐方式
                if(replace.advance.extend_method == SJGReplaceGroup.CIRCLE
                    ||replace.advance.extend_method==SJGReplaceGroup.RECT){
                    this.adjustLayoutOfReplaceGroup_text(<TextExtObj>this.children[0]);        
                }
                    
            }            
        }else{
            // 强制对齐
            if(replace.advance.force_align==SJGReplaceGroupAdvance.FORCE_ALIGN_TEXT_HEAD){
                // 强制对齐把抬头压到锚点上
                this.adjustLayout_force_head(replace);
                
            } else if(replace.advance.force_align==SJGReplaceGroupAdvance.FORCE_ALIGN_IMAGE){
                // 强制对齐把图片压到锚点上
                this.adjustLayout_force_image(replace);
            }
        }
        
    }
    // 强制对齐把图片压到锚点上
    private adjustLayout_force_image(replace: SJGReplaceGroup=null):void{
        // 找到图片
        var imgs: number[]=this.getChildOfType(GCJ_CLASS_TYPE.CLASS_TYPE_ImageObj,false,false);
        if(imgs.length!=1) return;
        var i: ImageObj=<ImageObj>this.getGlobalData().objManager().getObject(imgs[0]);
        // 找到文字
        var t: TextExtObj=null;
        var txts: number[]=this.getChildOfType(GCJ_CLASS_TYPE.CLASS_TYPE_TextExtObj,false,false);
        if(txts.length>1) return;
        if(txts.length==1){
            // 不处理同时有图片和文字抬头的情况
            var txt: TextExtObj=<TextExtObj>this.getGlobalData().objManager().getObject(txts[0]);
            if(txt.head) return;
            
            // 含有图片和文字
            t=txt;
        }
        // 将图片压到锚点上。
        var offset: Point=this.adjustImageInForceMode(i);
        // 处理文字的对齐
//        var offset: Point=new Point();
        if(txt){
            this.adjustLayoutOfReplaceGroup_text(txt,offset,replace);    
        }
           
    }
    // 在强制模式下，调整图片到相应的位置以便压到锚点上
    // 返回:图片中心点对齐到锚点，正文所需要的偏移
    private adjustImageInForceMode(img:ImageObj):Point{
        img.pos.x=(this.align.x-this.pos.x)-img.pos.w/2;
        img.pos.y=(this.align.y-this.pos.y)-img.pos.h/2;
        
        
        var offset: Point=new Point();
        offset.x=img.pos.w/2;
        offset.y=img.pos.h/2;
        return offset;
    }
    // 强制对齐把抬头压到锚点上
    private adjustLayout_force_head(replace:SJGReplaceGroup=null):void{
        // 找到文字，根据抬头和对齐类型计算文字的偏移
        var txts:number[] = this.getChildOfType(GCJ_CLASS_TYPE.CLASS_TYPE_TextExtObj,false,false);
        if(txts.length==1){
            var txt: TextExtObj=<TextExtObj>this.getGlobalData().objManager().getObject(txts[0]);
            if(txt.head){
                var offset: Point=this.adjustHeadOfTextInForceMode(txt);
                this.adjustLayoutOfReplaceGroup_text(txt,offset,replace);                
            }
        }
    }
    // 在强制模式下，调整抬头到相应的位置以便压到锚点上
    // 返回:抬头中心点对齐到锚点，正文所需要的偏移
    private adjustHeadOfTextInForceMode(text: TextExtObj):Point{
        switch(this.align.alignType) {
            case ObjPositionAlign.ALIGN_POINT_0:
                // 抬头需要对齐到文字的右上角
                text.headPos=new ObjRelativePosType(ObjPositionAlign.ALIGN_POINT_4,
                    ObjPositionAlign.ALIGN_POINT_0);
                text.headOffset=new Point(0,0);
                text.headAlignTo=TextExtObj.HEAD_ALIGN_TO_TITLE_AND_TEXT;

                break;
            case ObjPositionAlign.ALIGN_POINT_1:
                text.headPos=new ObjRelativePosType(ObjPositionAlign.ALIGN_POINT_5,
                    ObjPositionAlign.ALIGN_POINT_1);
                text.headOffset=new Point(0,0);
                text.headAlignTo=TextExtObj.HEAD_ALIGN_TO_TITLE_AND_TEXT;
                
                break;
            case ObjPositionAlign.ALIGN_POINT_2:
                text.headPos=new ObjRelativePosType(ObjPositionAlign.ALIGN_POINT_6,
                    ObjPositionAlign.ALIGN_POINT_2);
                text.headOffset=new Point(0,0);
                text.headAlignTo=TextExtObj.HEAD_ALIGN_TO_TITLE_AND_TEXT;
                break;
            case ObjPositionAlign.ALIGN_POINT_3:
                text.headPos=new ObjRelativePosType(ObjPositionAlign.ALIGN_POINT_7,
                    ObjPositionAlign.ALIGN_POINT_3);
                text.headOffset=new Point(0,0);
                text.headAlignTo=TextExtObj.HEAD_ALIGN_TO_TITLE_AND_TEXT;
                break;
            case ObjPositionAlign.ALIGN_POINT_4:
                text.headPos=new ObjRelativePosType(ObjPositionAlign.ALIGN_POINT_0,
                    ObjPositionAlign.ALIGN_POINT_4);
                text.headOffset=new Point(0,0);
                text.headAlignTo=TextExtObj.HEAD_ALIGN_TO_TITLE_AND_TEXT;
                break;
            case ObjPositionAlign.ALIGN_POINT_5:
                text.headPos=new ObjRelativePosType(ObjPositionAlign.ALIGN_POINT_1,
                    ObjPositionAlign.ALIGN_POINT_5);
                text.headOffset=new Point(0,0);
                text.headAlignTo=TextExtObj.HEAD_ALIGN_TO_TITLE_AND_TEXT;
                break;
            case ObjPositionAlign.ALIGN_POINT_6:
                text.headPos=new ObjRelativePosType(ObjPositionAlign.ALIGN_POINT_2,
                    ObjPositionAlign.ALIGN_POINT_6);
                text.headOffset=new Point(0,0);
                text.headAlignTo=TextExtObj.HEAD_ALIGN_TO_TITLE_AND_TEXT;
                break;
            case ObjPositionAlign.ALIGN_POINT_7:
                text.headPos=new ObjRelativePosType(ObjPositionAlign.ALIGN_POINT_3,
                    ObjPositionAlign.ALIGN_POINT_7);
                text.headOffset=new Point(0,0);
                text.headAlignTo=TextExtObj.HEAD_ALIGN_TO_TITLE_AND_TEXT;
                break;
            case ObjPositionAlign.ALIGN_POINT_8:
                text.headPos=new ObjRelativePosType(ObjPositionAlign.ALIGN_POINT_8,
                    ObjPositionAlign.ALIGN_POINT_8);
                text.headOffset=new Point(0,0);
                text.headAlignTo=TextExtObj.HEAD_ALIGN_TO_TITLE_AND_TEXT;
                break;
            default:
                break;
        }
        // 重置各字符bx、by，以及各段高宽
        text.refresh();
        
        // 抬头的中心点离正文点距离
        var offset: Point=new Point();
        offset.x=text.head.pos.w/2;
        offset.y=text.head.pos.h/2;
        return offset;
    }
    
    // 根据kernelObj上的对齐属性调整内部对象的布局
    // 注意：offset会根据align自动添加正负号，保证在任意角度都向圆形外扩展
    private adjustLayoutOfReplaceGroup_text(text: TextExtObj, offset:Point=new Point(0,0), replace: SJGReplaceGroup=null): void {
        // 将文字对齐到对齐点上，调整文字自身对齐方式
        switch(this.align.alignType){
            case ObjPositionAlign.ALIGN_POINT_0:
                // 文字在父容器中水平居中、垂直居顶、文字水平居中、垂直居顶
                text.pos.x=(this.pos.w-text.pos.w)/2;
                text.pos.y=0                        + offset.y;
                text.style.po=TextObj.POSITION_CENTER;   
                text.style.vpo=TextObj.V_POSITION_TOP;
                break;
            case ObjPositionAlign.ALIGN_POINT_1:
                // 文字在父容器中水平居右、垂直居顶、文字水平右对齐、垂直居顶
                text.pos.x=this.pos.w-text.pos.w    - offset.x;
                text.pos.y=0                        + offset.y;
                text.style.po=TextObj.POSITION_RIGHT;
                text.style.vpo=TextObj.V_POSITION_TOP;
                break;
            case ObjPositionAlign.ALIGN_POINT_2:
                // 文字在父容器中水平居右、垂直居中、文字水平右对齐、垂直居中
                text.pos.x=this.pos.w-text.pos.w    - offset.x;
                text.pos.y=(this.pos.h-text.pos.h)/2;
                text.style.po=TextObj.POSITION_RIGHT;
                text.style.vpo=TextObj.V_POSITION_CENTER;
                break;
            case ObjPositionAlign.ALIGN_POINT_3:
                // 文字在父容器中水平居右、垂直居底、文字水平右对齐、垂直居底
                text.pos.x=this.pos.w-text.pos.w - offset.x;
                text.pos.y=this.pos.h-text.pos.h -  offset.y;
                text.style.po=TextObj.POSITION_RIGHT;
                text.style.vpo=TextObj.V_POSITION_BOTTOM;
                break;
            case ObjPositionAlign.ALIGN_POINT_4:
                // 文字在父容器中水平居中、垂直居底、文字水平居中、垂直居底
                text.pos.x=(this.pos.w-text.pos.w)/2;
                text.pos.y=this.pos.h-text.pos.h - offset.y;
                text.style.po=TextObj.POSITION_CENTER;
                text.style.vpo=TextObj.V_POSITION_BOTTOM;
                break;
            case ObjPositionAlign.ALIGN_POINT_5:
                // 文字在父容器中水平居左、垂直居底、文字水平居右、垂直居底
                text.pos.x=0                    + offset.x;
                text.pos.y=this.pos.h-text.pos.h- offset.y;
                text.style.po=TextObj.POSITION_LEFT;
                text.style.vpo=TextObj.V_POSITION_BOTTOM;
                break;
            case ObjPositionAlign.ALIGN_POINT_6:
                // 文字在父容器中水平居左、垂直居中、文字水平居右、垂直居中
                text.pos.x=0                    + offset.x;
                text.pos.y=(this.pos.h-text.pos.h)/2;
                text.style.po=TextObj.POSITION_LEFT;
                text.style.vpo=TextObj.V_POSITION_CENTER;
                break;
            case ObjPositionAlign.ALIGN_POINT_7:
                // 文字在父容器中水平居左、垂直居顶、文字水平居右、垂直居顶
                text.pos.x=0                    + offset.x;
                text.pos.y=0                    + offset.y;               
                text.style.po=TextObj.POSITION_LEFT;
                text.style.vpo=TextObj.V_POSITION_TOP;
                break;
            case ObjPositionAlign.ALIGN_POINT_8:
                // 文字在父容器中水平居中、垂直居中、文字水平居中、垂直居中
                text.pos.x=(this.pos.w-text.pos.w)/2;
                text.pos.y=(this.pos.h-text.pos.h)/2;
                text.style.po=TextObj.POSITION_CENTER;
                text.style.vpo=TextObj.V_POSITION_CENTER;
                break;
            default:
                break;
        }
        // 重置各字符bx、by，以及各段高宽
        text.refresh();
        
    }
    //  升级数据，需要升级到接口实现
    public upgradeData() { 
        // 获取小标题对应的正文的id
        var map=this.getOldTilteMatchedText();
        
        // 升级TextObj到TextExObj,保持id不变
        var txts:Array<number> = this.getChildOfType(GCJ_CLASS_TYPE.CLASS_TYPE_TextObj,false,false);
        // 先升级正文
        for(var i=0;i<txts.length;i++){
            var old: TextObj=<TextObj>this.getGlobalData().objManager().getObject(txts[i]);
            if(!old) continue;
            
            if(old.tt!=TextObj.TEXT_TYPE_NORMAL) continue;
            
            // 根据旧文字创建新文字，保持id不变
            var newTxt: TextExtObj=TextExtObj.fromTextObj(old , this.getGlobalData());
            
            
            // 更新对象管理器
            this.getGlobalData().objManager().saveObject(newTxt);
            // 更新编组中旧文字的引用为新文字
            this.updateChildRef(old.id,newTxt);
        }
        
        // 再升级小标题，并合并到正文上
        var txts: Array<number>=this.getChildOfType(GCJ_CLASS_TYPE.CLASS_TYPE_TextObj,false,false);
        for(var i=0;i<txts.length;i++) {
            var old: TextObj=<TextObj>this.getGlobalData().objManager().getObject(txts[i]);
            if(!old) continue;
            
            if(old.tt!=TextObj.TEXT_TYPE_HEADLINE) continue;
            
            
            // 如果父的父是ReplaceGroupObj，才需要合并
            if(!old.parent||!old.parent.parent||old.parent.parent.ct!=GCJ_CLASS_TYPE.CLASS_TYPE_ReplaceGroupObj)
                continue;
                
               
            
            // 删除编组中旧文字
            this.removeChild(old.id);
            
            // 获取小标题对应的正文的id
            var matchId: number=map[old.id];
            if(!matchId) continue;
            
            // 添加旧文字到新型文字上
            var txtExt:TextExtObj=<TextExtObj>this.getGlobalData().objManager().getObject(matchId);
            txtExt.addTitleFromOld(old);
        }
        
        // fix bug
        var newTxtIds: Array<number>=this.getChildOfType(GCJ_CLASS_TYPE.CLASS_TYPE_TextExtObj,false,false);
        for(var i=0;i<newTxtIds.length;i++) {
            var newTxt: TextExtObj=<TextExtObj>this.getGlobalData().objManager().getObject(newTxtIds[i]);
            if(newTxt && newTxt.title) {
                var newTxtTitle: TextExtObj=<TextExtObj>newTxt.title;
                newTxtTitle.tt=TextExtObj.TEXT_TYPE_TITLE;
            }
        }
        
        // 处理子
        for(var q in this.children) {
            var child: ObjBase=<ObjBase>this.children[q];
            child.upgradeData();
        }
    }
    // 获取小标题对应的正文的id
    // 返回map：[titleId-textId]
    private getOldTilteMatchedText():Object{
        var map=new Object();
        
        
        var lastTitle=null;
        var lastText=null;
        var txts: Array<number>=this.getChildOfType(GCJ_CLASS_TYPE.CLASS_TYPE_TextObj,false,false);
        for(var i=0;i<txts.length;i++) {
            var old: TextObj=<TextObj>this.getGlobalData().objManager().getObject(txts[i]);
            if(!old) continue;
            
            if(old.tt==TextObj.TEXT_TYPE_HEADLINE){
                lastTitle=txts[i];
            } else if(old.tt==TextObj.TEXT_TYPE_NORMAL){
                lastText=txts[i];
            }
            
            if(lastTitle&&lastText){
                map[lastTitle]=lastText;        
                
                lastTitle=null;
                lastText=null;
            }
        }
        
        return map;
    }

    // 根据id查找对象
    public getChildById(objId) {
        var ret=super.getChildById(objId);
        if(ret) return ret;

        var len=this.children.length;
        for(var i=0;i<len;i++) {
            var one: ObjBase=<ObjBase> (this.children[i]);
            ret=one.getChildById(objId);
            if(ret){
                return ret;
            }
        }
        return null;
    }

//SJG_MARK_APPEND--------------------

    /* 检查数据的有效性.
     * 方式:GET
     * 参数:pc:1表示从pc来的请求/为空或者其它值表示从手机来的请求
     * 参数:docId:用户文档id
     * 返回:对象，属性如下：
     *          error:错误内容，null表示没有错误
     *          message:消息
     * */
    public validate() {
        var ret = {error:null,message:''};
        var len=this.children.length;
        for(var i=0;i<len;i++) {
            var one: ObjBase=this.children[i];
            var t = one.validate();

            if(t.error){
                ret.error=t.error;
            }
            ret.message += t.message;
        }


        return ret;
    }

}//SJG_MARK_END-------------------------